<template>
  <div
    class="online-query-form"
    :style="{ height: height ? height : '100%', width: '100%' }"
    v-show="isReady"
  >
    <el-container>
      <el-aside
        width="265px"
        class="left-panel"
        v-if="leftWidget != null && form2.leftTreeRightTable"
        @click.stop="onLeftWidgetClick"
      >
        <div class="title">
          <el-row align="middle" style="flex-wrap: nowrap">
            <span class="name">{{ leftWidget.showName }}</span>
            <el-input
              class="search round-search"
              :prefix-icon="Search"
              v-model="leftFilter"
              clearable
              :size="layoutStore.defaultFormItemSize"
              style="border-radius: 16px"
              :placeholder="'输入' + leftWidget.showName"
            />
          </el-row>
        </div>
        <el-scrollbar class="custom-scroll tree" style="flex-grow: 1">
          <div
            class="widget-item"
            :class="{ active: dialogParams.isEdit && currentWidget === leftWidget }"
          >
            <OnlineCustomWidget
              :widget="leftWidget"
              :ref="leftWidget.variableName"
              :value="getWidgetValue(leftWidget)"
              @input="val => onValueChange(leftWidget, val as ANY_OBJECT)"
              @change="onLeftWidgetChange"
            />
          </div>
        </el-scrollbar>
      </el-aside>
      <el-main class="table-panel" style="overflow: hidden">
        <OnlineFilterBox
          class="query-filter-box"
          :isEdit="dialogParams.isEdit"
          ref="filterBox"
          style="margin-bottom: 16px"
          :itemWidth="form2.filterItemWidth || 350"
          v-model:widgetList="activeWidgetList"
          :formData="formData"
          :operationList="activeOperationList"
          @widgetClick="onWidgetClick"
          @search="refreshTable(true)"
          @reset="onReset"
          @copy="onCopyWidget"
          @delete="onDeleteWidget"
          @operationClick="onOperationClick"
        >
        </OnlineFilterBox>
        <div
          class="query-table-box custom-widget-item widget-item"
          style="padding: 0px"
          :class="{ active: dialogParams.isEdit && currentWidget === queryTable }"
          @click.stop="onTableClick"
        >
          <OnlineCustomTable
            ref="tableWidget"
            :dataList="queryTableWidget.dataList"
            :isEdit="dialogParams.isEdit"
            :widget="queryTable"
            :singleSelect="true"
            :operationList="activeOperationList"
            :getTableIndex="queryTableWidget.getTableIndex"
            :sortChange="queryTableWidget.onSortChange"
            :onRadioChange="onRadioChange"
            :supportAutoEditNext="false"
            :supportCustomQuery="false"
            @operationClick="onOperationClick"
            @refresh="refreshTable(false)"
            @widgetClick="onWidgetClick"
            @updateChildWidgetList="onChildWidgetChange"
            @cell-click="onCellClick"
          >
            <template v-slot:pagination>
              <el-row type="flex" align="middle" style="padding: 16px 0px">
                <el-pagination
                  v-if="queryTable && queryTable.props.paged"
                  :total="queryTableWidget.totalCount"
                  :current-page="queryTableWidget.currentPage"
                  :page-size="queryTableWidget.pageSize"
                  :page-sizes="[10, 20, 50, 100]"
                  layout="total, prev, pager, next"
                  @current-change="queryTableWidget.onCurrentPageChange"
                  @size-change="queryTableWidget.onPageSizeChange"
                />
                <div style="flex: 1; width: 16px"></div>
                <div>
                  <el-button @click="onCancel">取消</el-button>
                  <el-button
                    type="primary"
                    :size="layoutStore.defaultFormItemSize"
                    @click="onSubmit()"
                  >
                    确认选择
                  </el-button>
                </div>
              </el-row>
            </template>
          </OnlineCustomTable>
        </div>
      </el-main>
    </el-container>
  </div>
</template>

<script setup lang="ts">
import { Search } from '@element-plus/icons-vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
import { ANY_OBJECT } from '@/types/generic';
import {
  OnlineFormEventType,
  SysCustomWidgetBindDataType,
  SysCustomWidgetOperationType,
} from '@/common/staticDict';
import { SysOnlineColumnFilterType } from '@/common/staticDict/online';
import { post, download, get } from '@/common/http/request';
import OnlineCustomTable from '@/online/components/OnlineCustomTable.vue';
import OnlineCustomWidget from '@/online/components/OnlineCustomWidget.vue';
import { useTable } from '@/common/hooks/useTable';
import { TableOptions } from '@/common/types/pagination';
import { API_CONTEXT } from '@/api/config';
import widgetData from '@/online/config/index';
import { useLayoutStore, useLoginStore } from '@/store';
import { useDict } from '../../hooks/useDict';
import { useForm } from '../hooks/useForm';
// import OnlineFilterBox from './OnlineFilterBox.vue';
import OnlineFilterBox from '@/online/components/OnlineFilterBox.vue';

const router = useRouter();
const leftFilter = ref<string>();

const emit = defineEmits<{
  widgetClick: [ANY_OBJECT | null];
  tableClick: [ANY_OBJECT];
  radioSelectChanged: [ANY_OBJECT];
  submit: [];
  cancel: [];
}>();

const props = withDefaults(
  defineProps<{
    formConfig: ANY_OBJECT;
    height?: string;
    // 主表数据
    masterTableData?: ANY_OBJECT;
    // 是否表单编辑模式
    isEdit?: boolean;
    readOnly?: boolean;
    // 当前选中组件
    currentWidget?: ANY_OBJECT | null;
    // 需要编辑数据，如果是null则是新增
    rowData?: ANY_OBJECT;
    // 是否全屏弹窗
    fullscreen?: boolean;
    selectedColumn?: string;
    selectedValue?: string;
    extraData?: ANY_OBJECT;
    mode?: string;
  }>(),
  {
    isEdit: false,
    readOnly: false,
    fullscreen: false,
  },
);
const layoutStore = useLayoutStore();
const { getDictDataList } = useDict();

const refreshTable = (reloadData = false) => {
  if (dialogParams.value.isEdit) return;
  if (reloadData) {
    queryTableWidget.refreshTable(true, 1);
  } else {
    queryTableWidget.refreshTable();
  }
};

const {
  isReady,
  dialogParams,
  form: form2,
  formData,
  getWidgetValue,
  getWidgetVisible,
  onValueChange,
  onWidgetValueChange,
  getDropdownParams,
  checkOperationPermCode,
  checkOperationDisabled,
  checkOperationVisible,
  cloneWidget,
  handlerOperation,
  loadOnlineFormConfig,
  initPage,
  initFormWidgetList,
  getIgnoreMaskFields,
  onPrint,
  onStartFlow,
  handlerScriptOperation,
  showDialog,
  showOnlineDialog,
  instanceData,
} = useForm({
  props,
  router,
  refresh: refreshTable,
});

provide('form', () => {
  return {
    ...form2.value,
    mode: props.mode || 'pc',
    isEdit: dialogParams.value.isEdit,
    readOnly: dialogParams.value.readOnly,
    formData: formData,
    getWidgetValue: getWidgetValue,
    getWidgetVisible: getWidgetVisible,
    onValueChange: onValueChange,
    onWidgetValueChange: onWidgetValueChange,
    getDropdownParams: getDropdownParams,
    checkOperationPermCode: checkOperationPermCode,
    checkOperationDisabled: checkOperationDisabled,
    checkOperationVisible: checkOperationVisible,
    cloneWidget: cloneWidget,
    onPrint: onPrint,
    onStartFlow: onStartFlow,
    handlerScriptOperation: handlerScriptOperation,
    handlerOperation: handlerOperation,
    getIgnoreMaskFields: getIgnoreMaskFields,
    getDictDataList: getDictDataList,
    loadOnlineFormConfig: loadOnlineFormConfig,
    isActive: (widget: ANY_OBJECT) => {
      return props.currentWidget === widget;
    },
    getWidgetObject: widgetData.getWidgetObject,
    filter: {
      name: leftFilter.value,
    },
    instanceData: () => instanceData,
  };
});

const tableWidget = ref();
const selectRows = ref<ANY_OBJECT[] | ANY_OBJECT>([]);

const activeWidgetList = computed(() => {
  return form2.value.widgetList;
});

const onChildWidgetChange = val => {
  queryTable.value.childWidgetList = val;
};

const onCellClick = (row, table) => {
  if (table) {
    table.setRadioRow(row);
    onRadioChange(row);
  }
};

const getQueryParamItem = (widget: ANY_OBJECT) => {
  if (widget.bindData.dataType !== SysCustomWidgetBindDataType.Column || widget.column == null)
    return null;
  let column = widget.column;
  let paramValue = getWidgetValue(widget);
  if (
    paramValue == null ||
    paramValue === '' ||
    (Array.isArray(paramValue) && paramValue.length === 0)
  )
    return null;
  let temp: ANY_OBJECT = {
    tableName: widget.table.tableName,
    columnName: widget.column.columnName,
    filterType: widget.column.filterType,
    columnValue:
      widget.column.filterType !== SysOnlineColumnFilterType.RANFGE_FILTER ? paramValue : undefined,
  };

  if (column.filterType === SysOnlineColumnFilterType.RANFGE_FILTER) {
    temp.columnValueStart = paramValue[0];
    temp.columnValueEnd = paramValue[1];
  }

  return temp;
};

const getQueryParams = () => {
  let queryParams = [];
  if (Array.isArray(activeWidgetList.value)) {
    queryParams = activeWidgetList.value
      .map(widget => {
        return getQueryParamItem(widget);
      })
      .filter(item => item != null);
  }

  if (leftWidget.value != null) {
    let temp = getQueryParamItem(leftWidget.value);
    if (temp) queryParams.push(temp);
  }
  return queryParams;
};

const getQueryString = () => {
  if (tableWidget.value) {
    let queryTable = tableWidget.value;
    if (Array.isArray(tableWidget.value)) {
      queryTable = tableWidget.value[0];
    }
    if (queryTable) {
      return queryTable.getSearchString();
    }
  }
  return null;
};

const loadTableData = async (params: ANY_OBJECT) => {
  let table = form2.value.tableMap.get(queryTable.value.bindData.tableId);
  params.datasourceId = table.datasource.datasourceId;
  params.filterDtoList = getQueryParams();

  if (queryTable.value.relation != null) {
    params.relationId = table.relation.relationId;
  }
  let queryString = getQueryString();
  // 模糊查询
  if (
    Array.isArray(queryTable.value.props.likeQueryColumn) &&
    queryTable.value.props.likeQueryColumn.length > 0 &&
    queryString != null &&
    queryString !== ''
  ) {
    let queryColumn = queryTable.value.props.likeQueryColumn
      .map(item => {
        return item.join('.');
      })
      .join(',');
    if (!Array.isArray(params.filterDtoList)) params.filterDtoList = [];
    params.filterDtoList.push({
      columnName: queryColumn,
      filterType: 14,
      columnValue: queryString,
    });
  }
  // 脱敏设置
  params.ignoreMaskFields = getIgnoreMaskFields(queryTable.value);
  if (!Array.isArray(params.orderParam) || params.orderParam.length <= 0) {
    // Jie. 20050418 增加排序参数
    let { orderColumn, orderAsc } = queryTable.value.props;
    if (orderColumn) {
      params.orderParam = [
        {
          fieldName: orderColumn,
          asc: !!orderAsc,
        },
      ];
    }
  }

  if (
    !dialogParams.value.isEdit &&
    typeof queryTable.value.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA] === 'function'
  ) {
    params = await queryTable.value.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA](
      params,
      instanceData,
    );
  }
  if (params == null) {
    throw new Error();
  }

  let res;
  if (table.relation != null) {
    res = await post<ANY_OBJECT>(
      API_CONTEXT +
        '/online/onlineOperation/listByOneToManyRelationId/' +
        table.datasource.variableName,
      params,
    );
  } else {
    res = await post<ANY_OBJECT>(
      API_CONTEXT + '/online/onlineOperation/listByDatasourceId/' + table.datasource.variableName,
      params,
    );
  }

  if (
    !dialogParams.value.isEdit &&
    typeof queryTable.value.eventInfo[OnlineFormEventType.AFTER_LOAD_TABLE_DATA] === 'function'
  ) {
    res.data.dataList = await queryTable.value.eventInfo[OnlineFormEventType.AFTER_LOAD_TABLE_DATA](
      res.data.dataList,
      instanceData,
    );
  }
  let selectedRowNum = res.data.dataList.findIndex((x: ANY_OBJECT) => {
    if (props.selectedColumn) {
      return x[props.selectedColumn] === props.selectedValue;
    } else {
      return false;
    }
  });
  if (selectedRowNum >= 0) {
    //this.$forceUpdate();
    setTimeout(() => {
      if (tableWidget.value) tableWidget.value.setSelectedRow(selectedRowNum);
    }, 30);
  }

  return {
    dataList: res.data.dataList,
    totalCount: res.data.totalCount,
  };
};
const loadTableDataVerify = () => {
  return true;
};
const tableOptions: TableOptions<ANY_OBJECT> = {
  loadTableData: loadTableData,
  verifyTableParameter: loadTableDataVerify,
  paged: dialogParams.value.formConfig?.tableWidget?.props.paged,
};
const queryTableWidget = reactive(useTable(tableOptions));

const queryTable = computed<ANY_OBJECT>(() => {
  return form2.value.tableWidget;
});
const activeOperationList = computed(() => {
  return form2.value.operationList;
});

// const getTableStyle = computed(() => {
//   return {
//     padding:
//       dialogParams.value.isEdit && props.currentWidget === queryTable.value ? '5px' : undefined,
//     background:
//       dialogParams.value.isEdit && props.currentWidget === queryTable.value
//         ? 'rgba(64, 158, 255, 0.2)'
//         : undefined,
//   };
// });
const primaryColumnName = computed(() => {
  if (dialogParams.value.isEdit) return;
  let table = form2.value.tableMap.get(queryTable.value.bindData.tableId);
  if (table && Array.isArray(table.columnList)) {
    for (let i = 0; i < table.columnList.length; i++) {
      let column = table.columnList[i];
      if (column.primaryKey) {
        return column.columnName;
      }
    }
  }
  return null;
});

const onCancel = () => {
  emit('cancel');
};

const onSubmit = () => {
  emit('submit');
};
const onCopyWidget = (widget: ANY_OBJECT) => {
  activeWidgetList.value.push(widget);
};
const onDeleteWidget = (widget: ANY_OBJECT) => {
  ElMessageBox.confirm('是否删除此组件？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    let index = form2.value.widgetList.indexOf(widget);
    if (index !== -1) {
      form2.value.widgetList.splice(index, 1);
    }
    onWidgetClick(null);
  });
};
const onTableClick = () => {
  emit('tableClick', queryTable.value);
};
const onWidgetClick = (widget: ANY_OBJECT | null) => {
  emit('widgetClick', widget);
};
const onRadioChange = (rows: ANY_OBJECT) => {
  selectRows.value = rows;
  emit('radioSelectChanged', selectRows.value as ANY_OBJECT);
};
const onReset = () => {
  activeWidgetList.value.forEach(widget => {
    onValueChange(widget, undefined);
  });
  refreshTable(true);
};
const onBatchDelete = () => {
  if (selectRows.value.length <= 0) {
    ElMessage.error('请选择要批量删除的数据！');
    return;
  }
  ElMessageBox.confirm('是否删除选中数据？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    let table = form2.value.tableMap.get(queryTable.value.bindData.tableId);
    let params = {
      datasourceId: table.datasource.datasourceId,
      relationId: (table.relation || {}).relationId,
      dataIdList: selectRows.value.map((item: ANY_OBJECT) => {
        return item[primaryColumnName.value];
      }),
    };

    let httpCall;
    if (params.relationId) {
      httpCall = post(
        API_CONTEXT +
          '/online/onlineOperation/deleteBatchOneToManyRelation/' +
          table.datasource.variableName,
        params,
      );
    } else {
      httpCall = post(
        API_CONTEXT +
          '/online/onlineOperation/deleteBatchDatasource/' +
          table.datasource.variableName,
        params,
      );
    }
    httpCall
      .then(() => {
        ElMessage.success('删除成功！');
        refreshTable(true);
      })
      .catch(e => {
        console.warn(e);
      });
  });
};
const onDeleteRow = (row: ANY_OBJECT) => {
  ElMessageBox.confirm('是否删除当前数据？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    let table = form2.value.tableMap.get(queryTable.value.bindData.tableId);
    let params = {
      datasourceId: table.datasource.datasourceId,
      relationId: (table.relation || {}).relationId,
      dataId: row[primaryColumnName.value],
    };
    let httpCall = null;
    if (params.relationId) {
      httpCall = post(
        API_CONTEXT +
          '/online/onlineOperation/deleteOneToManyRelation/' +
          table.datasource.variableName,
        params,
      );
    } else {
      httpCall = post(
        API_CONTEXT + '/online/onlineOperation/deleteDatasource/' + table.datasource.variableName,
        params,
      );
    }

    httpCall
      .then(() => {
        ElMessage.success('删除成功！');
        refreshTable(true);
      })
      .catch(e => {
        console.warn(e);
      });
  });
};
const onExport = (operation: ANY_OBJECT) => {
  ElMessageBox.confirm('是否导出表格数据？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(async () => {
    let table = form2.value.tableMap.get(queryTable.value.bindData.tableId);
    let params = {
      datasourceId: table.datasource.datasourceId,
      relationId: (table.relation || {}).relationId,
      filterDtoList: getQueryParams(),
      exportInfoList: (operation.exportColumnList || []).sort(
        (val1: ANY_OBJECT, val2: ANY_OBJECT) => {
          return val1.showOrder - val2.showOrder;
        },
      ),
    };

    if (queryTable.value.relation != null) {
      params.filterDtoList.push({
        tableName: queryTable.value.table.tableName,
        columnName: queryTable.value.relation.slaveColumn.columnName,
        filterType: SysOnlineColumnFilterType.EQUAL_FILTER,
        columnValue: (dialogParams.value.masterTableData || {})[
          queryTable.value.relation.masterColumn.columnName
        ],
      });
    }

    if (
      !dialogParams.value.isEdit &&
      typeof queryTable.value.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA] === 'function'
    ) {
      params = await queryTable.value.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA](
        params,
        instanceData,
      );
    }

    if (params == null) {
      throw new Error();
    }
    try {
      if (params.relationId) {
        await download(
          API_CONTEXT +
            '/online/onlineOperation/exportByOneToManyRelationId/' +
            table.datasource.variableName,
          params,
          queryTable.value.showName + '.xlsx',
        );
      } else {
        await download(
          API_CONTEXT +
            '/online/onlineOperation/exportByDatasourceId/' +
            table.datasource.variableName,
          params,
          queryTable.value.showName + '.xlsx',
        );
      }
      ElMessage.success('导出成功！');
    } catch (e) {
      ElMessage.error(e);
    }
  });
};
const onOperationClick = (operation: ANY_OBJECT, row: ANY_OBJECT | null) => {
  if (dialogParams.value.isEdit) return;
  if (operation.type === SysCustomWidgetOperationType.BATCH_DELETE) {
    onBatchDelete();
  } else if (operation.type === SysCustomWidgetOperationType.DELETE) {
    if (row) onDeleteRow(row);
  } else if (operation.type === SysCustomWidgetOperationType.EXPORT) {
    onExport(operation);
  } else if (operation.type === SysCustomWidgetOperationType.PRINT) {
    if (row) onPrint(operation, row, null, queryTable.value.showName);
  } else {
    handlerOperation(operation, {
      isEdit: dialogParams.value.isEdit,
      rowData: row,
      masterTableData: dialogParams.value.masterTableData || row,
      callback: () => {
        refreshTable();
      },
    });
  }
};

const initFormData = () => {
  refreshTable(true);
};

onMounted(() => {
  isReady.value = false;
  if (!dialogParams.value.isEdit) {
    if (
      form2.value.eventInfo &&
      typeof form2.value.eventInfo[OnlineFormEventType.AFTER_CREATE_FORM] === 'function'
    ) {
      form2.value.eventInfo[OnlineFormEventType.AFTER_CREATE_FORM](instanceData);
    }
    initFormData();
  }
  isReady.value = true;
});

const leftWidget = computed(() => {
  return form2.value.leftWidget;
});

const onLeftWidgetClick = () => {
  emit('widgetClick', form2.value.leftWidget);
};

const onLeftWidgetChange = (val: ANY_OBJECT | undefined, dictData: ANY_OBJECT | null) => {
  if (val && leftWidget.value) {
    onValueChange(leftWidget.value, val);
    onWidgetValueChange(leftWidget.value, val, dictData);
    nextTick(() => {
      refreshTable(true);
    });
  }
};
</script>

<style scoped>
.header-logo {
  display: inline-block;
  width: 40px;
  height: 40px;
  margin-right: 8px;
  text-align: center;
  color: #fda834;
  background: rgb(255 119 0 / 10%);
  border-radius: 8px;
  line-height: 40px;
}
.el-divider--vertical {
  height: 26px;
  margin: 7px 15px;
}
.online-query-form {
  display: flex;
  flex-direction: column;
  background-color: #f5f8f9;
}
.online-query-form :deep(.vxe-body--row) {
  cursor: pointer;
}
.online-query-form :deep(.table-box) {
  padding: 16px;
  padding-bottom: 5px;
}
.table-wrap {
  display: flex;
  flex-direction: column;
  padding: 16px 24px;
  background-color: white;
  flex: 1;
}
.online-query-form .query-filter-box {
  flex-grow: 0;
  flex-shrink: 0;
}
.online-query-form .query-table-box {
  flex-shrink: 1;
  height: 200px;
  flex-grow: 1;
}
.left-panel {
  display: flex;
  flex-direction: column;
  background: white;
  border-right: 2px solid #e8e8e8;
  margin-right: 15px;
}

.left-panel .title {
  flex-shrink: 0;
  padding: 20px;
  font-size: 14px;
  color: #333;
  flex-grow: 0;
  font-weight: 400;
  border-bottom: 2px solid #e8e8e8;
}

.left-panel .title .name {
  flex-grow: 0;
  flex-shrink: 0;
}

.left-panel .title .search {
  flex-shrink: 1;
  min-width: 50px;
  margin-left: 10px;
  flex-grow: 1;
}

.round-search :deep(.el-input__wrapper) {
  border-radius: 16px;
}

.table-panel {
  display: flex;
  flex-direction: column;
}
</style>
